package com.tvunetworks.center.device.service.impl;

import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.util.MyUtil;
import com.tvunetworks.center.common.util.Result;
import com.tvunetworks.center.common.util.ResultUtil;
import com.tvunetworks.center.device.constant.DeviceConstant;
import com.tvunetworks.center.device.mapper.ExternalReceiverRelationMapper;
import com.tvunetworks.center.device.mapper.MyDeviceMapper;
import com.tvunetworks.center.device.model.ExternalReceiverRelation;
import com.tvunetworks.center.device.model.MyDevice;
import com.tvunetworks.center.device.service.DeviceService;
import com.tvunetworks.center.device.service.ExtService;
import com.tvunetworks.center.device.service.feign.RwsFeignService;
import com.tvunetworks.center.gs.model.Device;
import lombok.extern.slf4j.Slf4j;
import net.spy.memcached.MemcachedClient;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @program: tvucc-device
 * @description: ExtServiceImpl
 * @author lebronchen
 * @create: 2019-03-19 14:18
 **/
@Service
@Slf4j
public class ExtServiceImpl implements ExtService {

    @Value("${externalHead}")
    private String externalHead;
    @Value("${deviceInMemcacheTime}")
    private int deviceInMemcacheTime;
    @Value("${ext.type}")
    private String extType;

    @Autowired
    private MyDeviceMapper myDeviceMapper;
    @Autowired
    private ExternalReceiverRelationMapper externalReceiverRelationMapper;
    @Autowired
    @Qualifier("tpdsMemcacheClient")
    private MemcachedClient tpdsMemcacheClient;
    @Autowired
    private RwsFeignService rwsFeignService;
    @Autowired
    private DeviceService deviceService;

    @Override
    @Transactional
    public synchronized Result<String> addExt(Device device) {

        // 如果对方传了peerId 则使用对方的peerId
        // 添加原因是添加了 Rtil 类型的 source, 需要使用指定的 ID
        String peerId = device.getPeerId();
        if(StringUtils.isEmpty(peerId)){
            // 获取Ext peerId
            peerId = this.getNewExtPeerId();
        }

        // 统一转小写
        peerId = StringUtils.lowerCase(peerId);


        // 拼接url
        String url = device.getUrl();
        int p = url.indexOf("://");
        if (p != -1) {
            url = url.substring(0, p).toLowerCase() + url.substring(p);
        }
        // 入库
        MyDevice myDevice = new MyDevice();
        myDevice.setPeerId(peerId);
        myDevice.setName(device.getName());
        myDevice.setUrl(url);
        myDevice.setType(device.getType());
        myDevice.setStatus(LocalConstant.DeviceStatus.ONLINE);
        myDevice.setAvailable("0");
        myDevice.setPlatform("1002");
        myDevice.setTimeStamp(System.currentTimeMillis()+"");
        if(device.getRemark() !=null){
            myDevice.setRemark(device.getRemark());
        }

        if("SonyCameraT".equalsIgnoreCase(device.getType()) || "SonyCameraR".equalsIgnoreCase(device.getType())){
            String rtMappingId  = UUID.randomUUID().toString().substring(0,17).replaceAll("-","0")+peerId;
            myDevice.setRtMappingId(rtMappingId);
        }
        myDevice.setId(MyUtil.getUUID());
        myDeviceMapper.insert(myDevice);
        // 入memcache
        BeanUtils.copyProperties(myDevice, device);
        tpdsMemcacheClient.set(DeviceConstant.MemcacheKey.STATUS_FOR_GRIDWITCH + peerId, deviceInMemcacheTime, device);

        return ResultUtil.success(peerId);
    }

    @Override
    @Transactional
    public Result<String> addExtToReceiver(String rid, String extPeerId) {
        Device existDevice = deviceService.getCurrentDevice(extPeerId);
        if (existDevice == null) {
            return ResultUtil.error("101", "Ext not exist");
        }
        String sourceType = existDevice.getType();
        boolean isExt = false;
        String[] extTypes = extType.split(",");
        for (String type : extTypes) {
            if (StringUtils.equalsIgnoreCase(type, sourceType)) {
                isExt = true;
            }
        }
        if (!isExt) {
            log.error("addExtToReceiver device not ext rid:[{}] sourcePeerId:[{}] sourceType:[{}]", rid, extPeerId, sourceType);
            return ResultUtil.error("102", "Device not ext");
        }

        ExternalReceiverRelation relation = new ExternalReceiverRelation();
        relation.setRId(rid);
        relation.setFullId(extPeerId);
        List<ExternalReceiverRelation> existRelation = externalReceiverRelationMapper.select(relation);
        if (existRelation != null && existRelation.size() > 0) {
            return ResultUtil.success();
        }
        relation.setId(MyUtil.getUUID());
        externalReceiverRelationMapper.insert(relation);

        deviceService.preloadExtXToR(rid);
        return ResultUtil.success();
    }
    @Override
    @Transactional
    public Result<String> addEventExtToReceiver(String rid, String extPeerId,String type) {
//        Device existDevice = deviceService.getCurrentDevice(extPeerId);
//        if (existDevice == null) {
//            return ResultUtil.error("101", "Ext not exist");
//        }
//        String sourceType = existDevice.getType();
        try {
            boolean isExt = true;

            if (!isExt) {
                log.error("addExtToReceiver device not ext rid:[{}] sourcePeerId:[{}] sourceType:[{}]", rid, extPeerId, type);
                return ResultUtil.error("102", "Device not ext");
            }

            ExternalReceiverRelation relation = new ExternalReceiverRelation();
            relation.setRId(rid);
            relation.setFullId(extPeerId);
            log.error("2-1.start send to R tid="+extPeerId+",and rid="+rid);
            List<ExternalReceiverRelation> existRelation = externalReceiverRelationMapper.select(relation);
            log.error("2-2.start send to R existRelation:[{}],AND rid:[{}]", existRelation, rid);
            if (existRelation != null && existRelation.size() > 0) {
                log.error("2-3.start send to R tid="+extPeerId+",and rid="+rid);
                return ResultUtil.success();
            }
            log.error("3.start send to R tid="+extPeerId+",and rid="+rid);

            relation.setId(MyUtil.getUUID());
            externalReceiverRelationMapper.insert(relation);
            log.error("4.start send to R tid="+extPeerId+",and rid="+rid);

            deviceService.preloadEventExtToR(rid);
        } catch (Exception e) {
            log.error("Exception====",e);
            log.error("msg:{},e:{}",e.getMessage(),e);
        }
        return ResultUtil.success();
    }

    @Override
    public Result<String> updateExt(Device device) {
        String peerId = device.getPeerId();
        Device existDevice = deviceService.getCurrentDevice(peerId);
        if (existDevice == null) {
            return ResultUtil.error("101", "Ext not exist");
        }
        if (!StringUtils.containsIgnoreCase(extType, existDevice.getType())) {
            return ResultUtil.error("102", "Device not ext");
        }
        if (StringUtils.equals(LocalConstant.DeviceStatus.LIVING, existDevice.getStatus())) {
            return ResultUtil.error("103", "Device is living");
        }

        // 将Ext设置到memcache
        existDevice.setName(device.getName());
        existDevice.setUrl(device.getUrl());
        existDevice.setRemark(device.getRemark());
        deviceService.setExtToMemcache(existDevice);

        // 更新ExternalReceiverRelation
        ExternalReceiverRelation relation = new ExternalReceiverRelation();
        relation.setFullId(peerId);
        List<ExternalReceiverRelation> existRelation = externalReceiverRelationMapper.select(relation);
        List<String> existRids = new ArrayList<>();
        if (!CollectionUtils.isEmpty(existRelation)) {
            for (ExternalReceiverRelation externalReceiverRelation : existRelation) {
                existRids.add(externalReceiverRelation.getRId());
            }
        }
        // 修改数据库
        myDeviceMapper.updateExt(peerId, device.getName(), device.getUrl(),device.getRemark());

        // 同步ext消息到R
        if (!CollectionUtils.isEmpty(existRids)) {
            for (String rid : existRids) {
                deviceService.preloadExtXToR(rid);
            }

        }
        return ResultUtil.success();
    }

    @Override
    public Result<String> deleteExt(String peerId) {
        Device existDevice = deviceService.getCurrentDevice(peerId);
        if (existDevice == null) {
            return ResultUtil.error("101", "Ext not exist");
        }
        if (!StringUtils.containsIgnoreCase(extType, existDevice.getType())) {
            return ResultUtil.error("102", "Device not ext");
        }
        if (StringUtils.equals(LocalConstant.DeviceStatus.LIVING, existDevice.getStatus())) {
            return ResultUtil.error("103", "Device is living");
        }

        // 在memcache删除Ext
        deviceService.deleteExtFromMemcache(peerId);

        // 更新ExternalReceiverRelation
        ExternalReceiverRelation relation = new ExternalReceiverRelation();
        relation.setFullId(peerId);
        List<ExternalReceiverRelation> existRelation = externalReceiverRelationMapper.select(relation);
        List<String> existRids = new ArrayList<>();
        if (!CollectionUtils.isEmpty(existRelation)) {
            for (ExternalReceiverRelation externalReceiverRelation : existRelation) {
                existRids.add(externalReceiverRelation.getRId());
            }
            externalReceiverRelationMapper.delete(relation);
        }
        // 同步ext消息到R
        if (!CollectionUtils.isEmpty(existRids)) {
            for (String rid : existRids) {
                deviceService.preloadExtXToR(rid);
            }

        }

        // 修改数据库
        myDeviceMapper.deleteByPrimaryKey(existDevice.getId());
        return ResultUtil.success();
    }

    /**
     * 供event执行结束使用
     * @param rid rid
     * @param sourceId  sourceId
     */
    public void deleteRExt(String rid,String sourceId){
        ExternalReceiverRelation relation = new ExternalReceiverRelation();
        relation.setFullId(sourceId);
        relation.setRId(rid);
        List<ExternalReceiverRelation> existRelation = externalReceiverRelationMapper.select(relation);
        if(existRelation !=null && existRelation.size()>0){
            externalReceiverRelationMapper.delete(relation);//删除本地source 和r关系
            deviceService.preloadExtXToR(rid);//触发从新下发ext到R
        }
    }


    @Override
    public Result<String> deleteGrid(String peerId) {
        Device existDevice = deviceService.getCurrentDevice(peerId);
        if (existDevice == null) {
            return ResultUtil.error("101", "Ext not exist");
        }
        if (!StringUtils.containsIgnoreCase(extType, existDevice.getType())) {
            return ResultUtil.error("102", "Device not ext");
        }
        if (StringUtils.equals(LocalConstant.DeviceStatus.LIVING, existDevice.getStatus())) {
            return ResultUtil.error("103", "Device is living");
        }

        // 在memcache删除Ext
        deviceService.deleteExtFromMemcache(peerId);
        // 修改数据库
        myDeviceMapper.deleteByPrimaryKey(existDevice.getId());
        return ResultUtil.success();
    }

    @Override
    public List<String> listExtBindedRids(String peerId) {
        return externalReceiverRelationMapper.listExtBindedRids(peerId);
    }

    @Override
    public void correlateExtPairedR(String peerId, String addRids, String removeRids) {
        Device device = deviceService.getCurrentDevice(peerId);
        if (device == null) {
            log.error("correlateExtPairedR device not exist peerId:[{}]", peerId);
            return;
        }
        if (!StringUtils.containsIgnoreCase(extType, device.getType())) {
            log.error("correlateExtPairedR device not ext peerId:[{}] type:[{}]", peerId, device.getType());
            return;
        }
        if (StringUtils.isNotBlank(addRids)) {
            String[] rids = addRids.split(",");
            for (String rid : rids) {
                ExternalReceiverRelation record = new ExternalReceiverRelation()
                        .setFullId(peerId)
                        .setRId(rid);
                List<ExternalReceiverRelation> list = externalReceiverRelationMapper.select(record);
                if (!CollectionUtils.isEmpty(list)) {
                    continue;
                }
                record.setId(MyUtil.getUUID());
                externalReceiverRelationMapper.insert(record);

                // 同步ext消息到R
                deviceService.preloadExtXToR(rid);
            }
        }
        if (StringUtils.isNotBlank(removeRids)) {
            String[] rids = removeRids.split(",");
            for (String rid : rids) {
                ExternalReceiverRelation record = new ExternalReceiverRelation()
                        .setFullId(peerId)
                        .setRId(rid);
                List<ExternalReceiverRelation> list = externalReceiverRelationMapper.select(record);
                if (CollectionUtils.isEmpty(list)) {
                    continue;
                }
                for (ExternalReceiverRelation externalReceiverRelation : list) {
                    externalReceiverRelationMapper.delete(externalReceiverRelation);
                }
                // 同步ext消息到R
                deviceService.preloadExtXToR(rid);
            }
        }
    }

    private String getNewExtPeerId(){
        String peerId = externalHead + "00000" + Long.toHexString((new Date()).getTime());
        MyDevice myDevice = new MyDevice();
        myDevice.setPeerId(peerId);
        List<MyDevice> exists = myDeviceMapper.select(myDevice);
        if (exists == null || exists.size() == 0) {
            return peerId;
        }
        return getNewExtPeerId();
    }
}
